﻿using System.Collections.Generic;

namespace Plugins.Threading
{
    public class PluginThreadSafeStack<T>
    {
        private Stack<T> _data = new Stack<T>();

        //private volatile int _bufferedCount;
        private volatile int _dataCount;
        //private int _bufferCount;
        //private T[] _buffer;
        //private object[] _bufferLock;

        //public ThreadSafeStack(int bufferCount)
        //{
        //    //_bufferCount = bufferCount;
        //    //_bufferLock = new object[_bufferCount];
        //    //_buffer = new T[_bufferCount];
        //    //for (int i = 0; i < _bufferCount; i++)
        //    //{
        //    //    _bufferLock[i] = new object();
        //    //}
        //}

        private List<T> _queue = new List<T>();
        //public void Clear()
        //{
        //    _dataCount = 0;
        //    _data.Clear();
        //    //_bufferedCount = 0;
        //    //for (int i = 0; i < _bufferCount; i++)
        //    //{
        //    //    _buffer[i] = default(T);
        //    //}
        //}
        public void Push(T item)
        {
            lock (this)
            {
                if (!object.Equals(item, default(T)))
                {
                    _dataCount++;
                    _data.Push(item);
                }
            }
            //if (!object.Equals(item, default(T)))
            //{
            //Monitor.Enter(this);
            //_dataCount++;
            //_data.Push(item);
            //T value = default(T);
            //do
            //{
            //    // gess, if it is not possible to aquire the lock
            //    if (Monitor.TryEnter(this))
            //    {
            //        if (_bufferedCount > 0)
            //        {
            //            for (int i = 0; i < _bufferCount; i++)
            //            {
            //                Monitor.Enter(_bufferLock[i]);
            //                if (!object.Equals(_buffer[i], default(T)))
            //                {
            //                    _dataCount++;
            //                    _data.Push(_buffer[i]);
            //                    _buffer[i] = default(T);
            //                    _bufferedCount--;
            //                }
            //            }
            //            for (int i = 0; i < _bufferCount; i++)
            //            {
            //                Monitor.Exit(_bufferLock[i]);
            //            }
            //        }
            //        _dataCount++;
            //        _data.Push(item);
            //        value = default(T);
            //        Monitor.Exit(this);
            //    }
            //    else
            //    {
            //        if (object.Equals(value, default(T)))
            //        {
            //            // write to the buffer
            //            for (int i = 0; i < _bufferCount; i++)
            //            {
            //                // gess, if it is possible to aquire the lock on the data slot
            //                if (Monitor.TryEnter(_bufferLock[i]))
            //                {
            //                    value = _buffer[i];
            //                    _buffer[i] = item;
            //                    _bufferedCount++;
            //                    Monitor.Exit(_bufferLock[i]);
            //                    break;
            //                }
            //            }
            //        }
            //    }
            //} while (!object.Equals(value, default(T)));
            //}
        }
        public int Count
        {
            get
            {
                return _dataCount/* + _bufferedCount*/;
            }
        }
        public T Pop()
        {
            T value = default(T);
            //if (_bufferedCount > 0)
            //{
            //    for (int i = 0; i < _bufferCount; i++)
            //    {
            //        if (Monitor.TryEnter(_bufferLock[i]))
            //        {
            //            if (!object.Equals(_buffer[i], default(T)))
            //            {
            //                value = _buffer[i];
            //                _buffer[i] = default(T);
            //                _bufferedCount--;
            //            }
            //            Monitor.Exit(_bufferLock[i]);
            //        }
            //        if (!object.Equals(value, default(T)))
            //        {
            //            return value;
            //        }
            //    }
            //}
            lock (this)
            {
                if (_dataCount > 0)
                {
                    _dataCount--;
                    value = _data.Pop();
                }
            }
            return value;
        }
    }
}
